import patchVnode from './patchVnode.js'
import creatElement from './creatElement.js'

function checkSameVnode(a, b) {
  console.log(a.data.key, b.data.key);
  return a.sel === b.sel && a.data.key === b.data.key
}
export default function updateChildren(parentElm, oldCh, newCh) {
  let oldStartIdx = 0 // 旧前
  let newStartIdx = 0 // 新前
  let oldEndIdx = oldCh.length - 1 // 旧后
  let newEndIdx = newCh.length - 1 // 新后
  let oldStartVnode = oldCh[oldStartIdx] // 旧前节点
  let oldEndVnode = oldCh[oldEndIdx] // 旧后节点
  let newStartVnode = newCh[newStartIdx] // 新前节点
  let newEndVnode = newCh[newEndIdx] // 新后节点
  let keyMap = null

  while (newStartIdx <= newEndIdx && oldStartIdx <= oldEndIdx) {
    // console.log(oldStartVnode, newStartVnode);
    // 首先不是判断命中，而是要掠过已经加undefined标记的东西
    if (oldStartVnode === null || oldCh[oldStartIdx] === undefined) {
      oldStartVnode = oldCh[++oldStartIdx]
    } else if (oldEndVnode === null || oldCh[oldEndIdx] === undefined) {
      oldEndVnode = oldCh[--oldEndIdx]
    } else if (newStartVnode === null || newCh[newStartIdx] === undefined) {
      newStartVnode = newCh[++newStartIdx]
    } else if (newEndVnode === null || newCh[newEndIdx] === undefined) {
      newEndVnode = newCh[--newEndIdx]
    } else if (checkSameVnode(oldStartVnode, newStartVnode)) {
      console.log('① 新前和旧前命中')
      patchVnode(oldStartVnode, newStartVnode)
      oldStartVnode = oldCh[++oldStartIdx]
      newStartVnode = newCh[++newStartIdx]

    } else if (checkSameVnode(oldEndVnode, newEndVnode)) {
      console.log('② 新后和旧后命中')
      patchVnode(oldEndVnode, newEndVnode)
      oldEndVnode = oldCh[--oldEndIdx]
      newEndVnode = newCh[--newEndIdx]

    } else if (checkSameVnode(oldStartVnode, newEndVnode)) {
      console.log('③ 新后和旧前命中')
      patchVnode(oldStartVnode, newEndVnode)
        /*
          新后与旧前（当命中3时，涉及到移动，移动新后（或旧前，此时新后===旧前）
          指针指向的结点到旧后指针指向的结点后面，旧前指针指向的结点设为undefined  
        */
      parentElm.insertBefore(oldStartVnode.elm, oldEndVnode.elm.nextSibling)
      oldStartVnode = oldCh[++oldStartIdx]
      newEndVnode = newCh[--newEndIdx]
    } else if (checkSameVnode(oldEndVnode, newStartVnode)) {
      console.log('④ 新前和旧后命中')
      patchVnode(oldEndVnode, newStartVnode)
        /*
          新前与旧后  （当4命中时，涉及到移动，移动**新前**（或旧后，此时新前===旧后）
          指针指向的结点到**旧前**指针指向的结点**前面**，旧后指针指向的结点设为undefined
        */
      parentElm.insertBefore(oldEndVnode.elm, oldStartVnode.elm)
      oldEndVnode = oldCh[--oldEndIdx]
      newStartVnode = newCh[++newStartIdx]
    } else {
      // 四种都没命中
      // 制作keyMap，缓存
      if (!keyMap) {
        keyMap = {}
          // 从 oldStartIdx 开始，到oldEndIdx结束，创建keyMap映射对象
        for (let i = oldStartIdx; i <= oldEndIdx; i++) {
          const key = oldCh[i].key
          if (key !== undefined) {
            keyMap[key] = i
          }
        }
      }
      // 寻找当前 newStartIdx指向的结点 在 keyMap 中映射的序号
      const idxInOld = keyMap[newStartVnode.key]
      if (idxInOld === undefined) {
        // 判断，如果idxInOld是undefined 表示它是全新的项
        // 被加入的项（就是newStartVnode这项）现在不是真实的DOM
        parentElm.insertBefore(creatElement(newStartVnode), oldStartVnode.elm)
      } else {
        // 判断，如果idxInOld不是undefined 表示它原来存在于老结点中，不是全新的项，而是需要移动的项
        const elmToMove = oldCh[idxInOld]
          // 比对新结点于老结点
        patchVnode(elmToMove, newStartVnode)
          // 把这项设置为undefined，表示已经处理完了
        oldCh[idxInOld] = undefined
          // 移动，调用insertBefore
        parentElm.insertBefore(elmToMove.elm, oldStartVnode.elm)
      }
      // 指针下移，只移动新的头
      newStartVnode = newCh[++newStartIdx]
    }
  }
  // 此时还剩余有新结点，要插入
  if (newStartIdx <= newEndIdx) {
    for (let i = newStartIdx; i <= newEndIdx; i++) {
      // newCh[i] 还不是真正的DOM，所以需要此处需要调用createElement
      console.log("自己写的");
      parentElm.insertBefore(creatElement(newCh[i]), oldCh[oldStartIdx])
    }
  } else if (oldStartIdx <= oldEndIdx) { // 此时还有老结点剩余，要删除
    for (let i = oldStartIdx; i <= oldEndIdx; i++) {
      if (oldCh[i]) parentElm.removeChild(oldCh[i].elm)
    }
  }

}